/*******************************************************************************
 * Package: com.hngtrust.iir.industry.service.impl
 * Type:    IndustryDataServiceImpl
 * Date:    2021-12-16 11:26
 *
 * Copyright (c) 2021 HUANENG GUICHENG TRUST CORP.,LTD All Rights Reserved.
 *
 * You may not use this file except in compliance with the License.
 *******************************************************************************/
package com.hngtrust.iir.industry.service.impl;

import com.hngtrust.iir.base.controller.vo.IndustryVO;
import com.hngtrust.iir.company.entity.IndustryIndicator;
import com.hngtrust.iir.company.entity.IndustryPerformance;
import com.hngtrust.iir.company.service.IndustryIndicatorService;
import com.hngtrust.iir.company.service.IndustryPerformanceService;
import com.hngtrust.iir.industry.controller.field.IndicatorField;
import com.hngtrust.iir.industry.controller.field.PerformanceField;
import com.hngtrust.iir.industry.controller.vo.ListIndicatorMapRespVO;
import com.hngtrust.iir.industry.controller.vo.ListIndicatorRespVO;
import com.hngtrust.iir.industry.controller.vo.ListPerformanceMapRespVO;
import com.hngtrust.iir.industry.service.IndustryDataService;
import com.hngtrust.iir.util.ListUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 行业数据分析
 * @author Chentianyong
 * @date 2021-12-16 11:26
 */
@Service
public class IndustryDataServiceImpl implements IndustryDataService {
    
    @Autowired
    private IndustryIndicatorService industryIndicatorService;
    
    @Autowired
    private IndustryPerformanceService industryPerformanceService;
    
    @Override
    public List<ListIndicatorMapRespVO> listIndicatorMap(IndustryVO req) {
        IndustryIndicator industryIndicator = new IndustryIndicator();
        industryIndicator.setGbIndCode(req.getCode());
        List<IndustryIndicator> list = industryIndicatorService.listIndicatorMap(industryIndicator);
        List<ListIndicatorMapRespVO> resp = new ArrayList<>();
        ListUtil<ListIndicatorMapRespVO> listUtil = BeanUtils.instantiateClass(ListUtil.class);
        listUtil.copyList(list,resp,ListIndicatorMapRespVO.class);
        //计算同比
        for(Integer i = 1;i < resp.size();i++){
            ListIndicatorMapRespVO obj = resp.get(i);
            ListIndicatorMapRespVO preObj = resp.get(i - 1);
            String preMonth = this.getPreMonth(obj.getRptdate().substring(0,6));
            if(!preMonth.equals(preObj.getRptdate().substring(0,6))){
                continue;
            }
            if(null != obj.getAcctRcv() && null != preObj.getAcctRcv() && preObj.getAcctRcv().compareTo(BigDecimal.ZERO) != 0){
                obj.setAcctRcvRate(obj.getAcctRcv().subtract(preObj.getAcctRcv()).divide(preObj.getAcctRcv(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getSInfoEmployee() && null != preObj.getSInfoEmployee() && preObj.getSInfoEmployee().compareTo(BigDecimal.ZERO) != 0){
                obj.setSInfoEmployeeRate(obj.getSInfoEmployee().subtract(preObj.getSInfoEmployee()).divide(preObj.getSInfoEmployee(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getOperRev() && null != preObj.getOperRev() && preObj.getOperRev().compareTo(BigDecimal.ZERO) != 0){
                obj.setOperRevRate(obj.getOperRev().subtract(preObj.getOperRev()).divide(preObj.getOperRev(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getTotProfit() && null != preObj.getTotProfit() && preObj.getTotProfit().compareTo(BigDecimal.ZERO) != 0){
                obj.setTotProfitRate(obj.getTotProfit().subtract(preObj.getTotProfit()).divide(preObj.getTotProfit(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getOperCost() && null != preObj.getOperCost() && preObj.getOperCost().compareTo(BigDecimal.ZERO) != 0){
                obj.setOperCostRate(obj.getOperCost().subtract(preObj.getOperCost()).divide(preObj.getOperCost(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getSellingDistExp() && null != preObj.getSellingDistExp() && preObj.getSellingDistExp().compareTo(BigDecimal.ZERO) != 0){
                obj.setSellingDistExpRate(obj.getSellingDistExp().subtract(preObj.getSellingDistExp()).divide(preObj.getSellingDistExp(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getTaxSurOps() && null != preObj.getTaxSurOps() && preObj.getTaxSurOps().compareTo(BigDecimal.ZERO) != 0){
                obj.setTaxSurOpsRate(obj.getTaxSurOps().subtract(preObj.getTaxSurOps()).divide(preObj.getTaxSurOps(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getFinExp() && null != preObj.getFinExp() && preObj.getFinExp().compareTo(BigDecimal.ZERO) != 0){
                obj.setFinExpRate(obj.getFinExp().subtract(preObj.getFinExp()).divide(preObj.getFinExp(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getGerlAdminExp() && null != preObj.getGerlAdminExp() && preObj.getGerlAdminExp().compareTo(BigDecimal.ZERO) != 0){
                obj.setGerlAdminExpRate(obj.getGerlAdminExp().subtract(preObj.getGerlAdminExp()).divide(preObj.getGerlAdminExp(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getTotTax() && null != preObj.getTotTax() && preObj.getTotTax().compareTo(BigDecimal.ZERO) != 0){
                obj.setTotTaxRate(obj.getTotTax().subtract(preObj.getTotTax()).divide(preObj.getTotTax(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getInventories() && null != preObj.getInventories() && preObj.getInventories().compareTo(BigDecimal.ZERO) != 0){
                obj.setInventoriesRate(obj.getInventories().subtract(preObj.getInventories()).divide(preObj.getInventories(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getAvgCurAssets() && null != preObj.getAvgCurAssets() && preObj.getAvgCurAssets().compareTo(BigDecimal.ZERO) != 0){
                obj.setAvgCurAssetsRate(obj.getAvgCurAssets().subtract(preObj.getAvgCurAssets()).divide(preObj.getAvgCurAssets(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getTotAssets() && null != preObj.getTotAssets() && preObj.getTotAssets().compareTo(BigDecimal.ZERO) != 0){
                obj.setTotAssetsRate(obj.getTotAssets().subtract(preObj.getTotAssets()).divide(preObj.getTotAssets(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getTotLiab() && null != preObj.getTotLiab() && preObj.getTotLiab().compareTo(BigDecimal.ZERO) != 0){
                obj.setTotLiabRate(obj.getTotLiab().subtract(preObj.getTotLiab()).divide(preObj.getTotLiab(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getSInfoNoLoss() && null != preObj.getSInfoNoLoss() && preObj.getSInfoNoLoss().compareTo(BigDecimal.ZERO) != 0){
                obj.setSInfoNoLossRate(obj.getSInfoNoLoss().subtract(preObj.getSInfoNoLoss()).divide(preObj.getSInfoNoLoss(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
            if(null != obj.getTotProfitLoss() && null != preObj.getTotProfitLoss() && preObj.getTotProfitLoss().compareTo(BigDecimal.ZERO) != 0){
                obj.setTotProfitLossRate(obj.getTotProfitLoss().subtract(preObj.getTotProfitLoss()).divide(preObj.getTotProfitLoss(),4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
            }
        
        }
        
        return resp;
    }
    
    @Override
    public List<ListPerformanceMapRespVO> listPerformanceMap(IndustryVO req) {
        IndustryPerformance industryPerformance = new IndustryPerformance();
        industryPerformance.setSasacIndCode(req.getCode());
        industryPerformance.setDataType(3); //平均值
        industryPerformance.setStatScope(1); //全行业
        List<IndustryPerformance> list = industryPerformanceService.listPerformanceMap(industryPerformance);
        List<ListPerformanceMapRespVO> resp = new ArrayList<>();
        ListUtil<ListPerformanceMapRespVO> listUtil = BeanUtils.instantiateClass(ListUtil.class);
        listUtil.copyList(list,resp,ListPerformanceMapRespVO.class);
        return resp;
    }
    
    @Override
    public List<ListIndicatorRespVO> listIndicator(IndustryVO req) throws Exception {
        IndustryIndicator industryIndicator = new IndustryIndicator();
        industryIndicator.setGbIndCode(req.getCode());
        List<IndustryIndicator> list = industryIndicatorService.listIndicatorMap(industryIndicator);
        if(list.isEmpty()){
            return null;
        }

        List<ListIndicatorRespVO> resp = this.changeRowToCol(list, IndicatorField.values());
        
        return resp;
    }
    
    @Override
    public List<ListIndicatorRespVO> listPerformance(IndustryVO req) throws Exception {
        IndustryPerformance industryPerformance = new IndustryPerformance();
        industryPerformance.setSasacIndCode(req.getCode());
        List<IndustryPerformance> list = industryPerformanceService.listPerformanceMap(industryPerformance);
        if(list.isEmpty()){
            return null;
        }
    
        List<ListIndicatorRespVO> resp = this.changeRowToCol(list, PerformanceField.values());
    
        return resp;
    }
    
    /**
     * 对数据做行列转换
     *
     * @param list 数据列表
     */
    private List<ListIndicatorRespVO> changeRowToCol(List<?> list,Object[] enumType) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException,
            InvocationTargetException {
        List<ListIndicatorRespVO> resp = new ArrayList<>();
    
        Object curObj = list.get(list.size() - 1);
        Object preObj = null;
        Object yoyObj = null;
        if(list.get(0) instanceof IndustryIndicator) {
            Method getRptdate = list.get(0).getClass().getMethod("getRptdate");
            String preMonth = this.getPreMonth(((String)getRptdate.invoke(curObj)).substring(0, 6));
            String yoyMonth = String.valueOf(Integer.valueOf(((String)getRptdate.invoke(curObj)).substring(0, 4)) - 1) + ((String)getRptdate.invoke(curObj)).substring(4, 6);
            for (Object obj : list) {
                if (((String)getRptdate.invoke(obj)).equals(preMonth)) {
                    preObj = obj;
                } else if (((String)getRptdate.invoke(obj)).equals(yoyMonth)) {
                    yoyObj = obj;
                }
            }
        }
        else if(list.get(0) instanceof IndustryPerformance) {
            Method getRptdate = list.get(0).getClass().getMethod("getRptDate");
            String yoyMonth = String.valueOf(Integer.valueOf(((String)getRptdate.invoke(curObj)).substring(0, 4)) - 1);
            for (Object obj : list) {
                if (((String)getRptdate.invoke(obj)).equals(yoyMonth)) {
                    yoyObj = obj;
                    preObj = obj;
                    break;
                }
            }
        }
        
        for(Object enumValue : enumType){
            String enumName = "";
            String enumCode = "";
            ListIndicatorRespVO obj = new ListIndicatorRespVO();
            if(list.get(0) instanceof IndustryIndicator){
                IndicatorField curEnum = (IndicatorField) enumValue;
                enumName = curEnum.getName();
                enumCode = curEnum.getCode();
            }
            else if(list.get(0) instanceof IndustryPerformance){
                PerformanceField curEnum = (PerformanceField) enumValue;
                enumName = curEnum.getName();
                enumCode = curEnum.getCode();
            }
            
            obj.setName(enumName);
            String name = enumCode.substring(0,1).toUpperCase()+enumCode.substring(1); //将属性的首字符大写，方便构造get，set方法
            Method m = list.get(0).getClass().getMethod("get"+name);
            
            BigDecimal curValue = (BigDecimal)m.invoke(curObj);
            obj.setCurValue(curValue);
            //更新时间
            m = list.get(0).getClass().getMethod("getUpdateTime");
            obj.setUpdateTime((Date)m.invoke(curObj));
    
            if(null != preObj) {
                m = list.get(0).getClass().getMethod("get"+name);
                BigDecimal value = (BigDecimal) m.invoke(preObj);
                obj.setPreValue(value);
                //环比
                if(null != value && null != curValue && value.compareTo(BigDecimal.ZERO) != 0) {
                    obj.setPreRate(curValue.subtract(value).divide(value, 4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
                }
            }
            
            if(null != yoyObj) {
                m = list.get(0).getClass().getMethod("get"+name);
                BigDecimal value = (BigDecimal) m.invoke(yoyObj);
                obj.setYoyValue(value);
                //同比
                if(null != value && null != curValue && value.compareTo(BigDecimal.ZERO) != 0) {
                    obj.setYoyRate(curValue.subtract(value).divide(value, 4, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)));
                }
            }
            resp.add(obj);
        }
        
        return resp;
    }
    
    
    /**
     * 取当前月份的前一月份
     */
    private String getPreMonth(String curMonth){
        if(curMonth.length() != 6){
            return null;
        }
        String preMonth = null;
        if(Integer.valueOf(curMonth.substring(4,6)) <= 1){
            preMonth = String.valueOf(Integer.valueOf(curMonth.substring(0,4)) - 1) + "12";
        }
        else{
            preMonth = String.valueOf(Integer.valueOf(curMonth) - 1);
        }
        
        return preMonth;
    }
}
